home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / aminet / mus / play / multiplsr.lha / player.asm < prev    next >
Assembly Source File  |  1992-09-14  |  65KB  |  2,301 lines

  1. * MultiPlayer
  2. * Copyright (C) 1992 Bryan Ford
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. *
  18. * I (the author of MultiPlayer) can be contacted on the Internet at
  19. * "bryan.ford@m.cc.utah.edu".  See "Player.doc" for other addresses.
  20. *
  21. * $Id: player.asm,v 5.1 92/09/14 18:43:30 BAF Exp $
  22. *
  23.  
  24. * System includes
  25.         include "exec/types.i"
  26.         include "exec/nodes.i"
  27.         include "exec/memory.i"
  28.         include "exec/interrupts.i"
  29.         include "exec/funcdef.i"
  30.         include "exec/exec_lib.i"
  31.         include "exec/execbase.i"
  32.         include "exec/ables.i"
  33.         include "hardware/cia.i"
  34.         include "hardware/intbits.i"
  35.         include "hardware/dmabits.i"
  36.         include "hardware/custom.i"
  37.         include "resources/cia.i"
  38.         include "dos/dos.i"
  39.         include "dos/dos_lib.i"
  40.         include "intuition/intuition_lib.i"
  41.         include "libraries/xpk.i"
  42.         include "bry/macros.i"
  43. _LVOAddICRVector        equ     -$06    ; LVO offsets for ciab.resource
  44. _LVORemICRVector        equ     -$0c
  45. _LVOAbleICR             equ     -$12
  46. _LVOSetICR              equ     -$18
  47.  
  48.  
  49.         include "player.i"
  50.  
  51.         code    text
  52.  
  53.         xref    toupper,toupperlong,stripblanks,isalpha
  54.         xref    allocaudio,freeaudio,intsongpos,intrepeat,clearflash
  55.         xref    _progload,_progstart
  56.         xref    NoteSys,NoteSysMasterVolBal
  57.  
  58.         xref    ntstart,trekstart,ntpackstart,ststart,npstart
  59.         xref    fcostart,fc14start,dssstart
  60.         xref    jamstart,soundmonstart
  61.         xref    oktastart,medstart
  62.         xref    soundstart
  63.  
  64.         xref    _LinkerDB,_SysBase,_DOSBase,_IntuitionBase,_BattMemBase,_XpkBase
  65.         xref    _sysflags,_playmode,_flashflags
  66.         xref    GlobSetByte,GlobSetWord,GlobSetLong
  67.         xref    mvolume,mbalance,mspeed,volume,balance,speed,modflags,filter
  68.         xref    _infowinattach,_infowindetach
  69.  
  70.         xdef    loadfile,unloadfile
  71.         xdef    loadmod,startmod,playmod,stopmod,endmod,contmod,contplaymod,setsong
  72.         xdef    _loadmod,_startmod,_playmod,_stopmod,_endmod,_contmod,_contplaymod,_setsong,_iscantcont
  73.         xdef    dienomem,diecorrupt,dieerrplay,diemes
  74.         xdef    settint,setnormtint,stoptint,hookfunc,dmawait
  75.         xdef    getfreqmodspeed,ntgetsongname,ntgetsongauthor,parseauthor,prepstring,addinfo
  76.         xdef    changetint,changetintcia
  77.         xdef    playervolume,playerspeed,_playervolume,_playerspeed
  78.         xdef    addinfo,addinfopad
  79.         xdef    allocmod,allocmodchip
  80.  
  81.         xdef    modtype,numsongs,cursong
  82.         xdef    modspec,modmem,modsize,modend
  83.         xdef    suppmem,suppsize,suppend
  84.         xdef    modname,authorname,modtypename,songcatalog
  85.         xdef    jumpforward,jumpback
  86.         xdef    _modtype,_modname,_authorname,_modtypename,_songcatalog,_playing,_infolist
  87.         xdef    _numsongs,_cursong,_songtime,_songendtime,_songpos,_songlen
  88.         xdef    _fadevol,_fadeinc
  89.         xdef    nocontinue              ; For rexxcont's benefit
  90.         xdef    nomemtext
  91.  
  92. *** gmodcheck - Check to see if a particular entry in the GMOD header is used
  93. * d0 = Offset of entrypoint
  94. * a5 = GMOD header
  95. * Returns: NZ if entrypoint is used, Z if it is nonexistent or do-nothing
  96. gmodcheck:
  97.         gmodbout d0,9$
  98.         cmp.w   #RTSINST,0(a5,d0.l)
  99.         rts
  100. 9$      cmp.l   d0,d0
  101.         rts
  102.  
  103. *** closeloadhan - Close any currently opened loadhan
  104. closeloadhan:
  105.         move.l  loadhan(a4),d1          ; Close the loading handle if opened
  106.         beq.s   1$
  107.         move.l  a6,-(sp)
  108.         move.l  _DOSBase(a4),a6
  109.         jsr     _LVOClose(a6)
  110.         clr.l   loadhan(a4)
  111.         move.l  (sp)+,a6
  112. 1$      rts
  113.  
  114.  
  115. *** allocmod/allocmodchip - Allocate memory attached to this module (freed when module is unloaded)
  116. * d0 = Amount of memory to allocate
  117. * Returns: d0 = Memory block, NULL on failure
  118. allocmodchip
  119.         move.l  #MEMF_CHIP,d0
  120.         bra     allocmod_in
  121. allocmod
  122.         moveq   #0,d1
  123. allocmod_in
  124.         move.l  a6,-(sp)
  125.         move.l  _IntuitionBase(a4),a6
  126.         jsr     _LVOAllocRemember(a6)
  127.         move.l  (sp)+,a6
  128.         rts
  129.  
  130.  
  131. *** loadfile - Load a file into a memory filespec
  132. * a0 = Pointer to filename
  133. * a1 = Pointer to filespec
  134. * Returns: NE if successful, EQ if file not found, die if other error
  135. loadfile:
  136.         apush
  137.         move.l  a1,a2
  138.  
  139.         tst.l   fs_Mem(a2)              ; See if we can decompress
  140.         bne.s   1$                      ; Can't decompress on a reload
  141.         move.l  _XpkBase(a4),d0
  142.         bne     5$
  143. 1$
  144.         move.l  a0,d1                   ; Open module
  145.         move.l  #MODE_OLDFILE,d2
  146.         move.l  _DOSBase(a4),a6
  147.         jsr     _LVOOpen(a6)
  148.         move.l  d0,loadhan(a4)
  149.         move.l  d0,d7
  150.         beq     99$
  151.  
  152.         move.l  d7,d1                   ; Seek to end of module
  153.         moveq   #0,d2
  154.         move.l  #OFFSET_END,d3
  155.         jsr     _LVOSeek(a6)
  156.         tst.l   d0
  157.         bne     dienofile
  158.  
  159.         move.l  d7,d1                   ; Seek back to beginning and find size
  160.         moveq   #0,d2
  161.         move.l  #OFFSET_BEGINNING,d3
  162.         jsr     _LVOSeek(a6)
  163.         move.l  d0,d6
  164.         ble     dienofile
  165.  
  166.         move.l  fs_Mem(a2),d0           ; See if the memory is already allocated
  167.         beq.s   2$
  168.         cmp.l   fs_FileSize(a2),d6      ; Make sure the file wasn't compressed
  169.         beq.s   3$
  170.         bra     diedontcompress
  171. 2$
  172.         move.l  _SysBase(a4),a6         ; Allocate memory
  173.         move.l  d6,d0
  174.         moveq   #MEMF_CHIP!MEMF_PUBLIC,d1
  175.         jsr     _LVOAllocMem(a6)
  176.         move.l  d0,fs_Mem(a2)
  177.         beq     dienocmem
  178.         move.l  d6,fs_FileSize(a2)
  179.         move.l  d6,fs_AllocSize(a2)
  180. 3$      move.l  d0,d2
  181.         add.l   d6,d0
  182.         move.l  d0,fs_EndMem(a2)
  183.  
  184.         move.l  _DOSBase(a4),a6         ; Load module
  185.         move.l  d7,d1
  186.         move.l  d6,d3
  187.         jsr     _LVORead(a6)
  188.         cmp.l   d0,d6
  189.         bne     dienofile
  190.  
  191.         bsr     closeloadhan            ; Close module
  192.  
  193.         bra     9$
  194.  
  195. 5$      move.l  d0,a6
  196.  
  197.         clr.l   -(sp)                   ; Set up the TagList
  198.         lea     xpkerrmsg(a4),a1
  199.         move.l  a1,-(sp)
  200.         move.l  #XPK_GetError,-(sp)
  201.         moveq   #1,d1
  202.         move.l  d1,-(sp)
  203.         move.l  #XPK_PassThru,-(sp)
  204.         moveq   #MEMF_CHIP,d1
  205.         move.l  d1,-(sp)
  206.         move.l  #XPK_OutMemType,-(sp)
  207.         lea     fs_FileSize(a2),a1
  208.         move.l  a1,-(sp)
  209.         move.l  #XPK_GetOutLen,-(sp)
  210.         lea     fs_AllocSize(a2),a1
  211.         move.l  a1,-(sp)
  212.         move.l  #XPK_GetOutBufLen,-(sp)
  213.         move.l  a2,-(sp)
  214.         move.l  #XPK_GetOutBuf,-(sp)
  215.         move.l  a0,-(sp)
  216.         move.l  #XPK_InName,-(sp)
  217.  
  218.         move.l  sp,a0                   ; Try to load the module
  219.         jsr     _LVOXpkUnpack(a6)
  220.         adda.w  #7*8+4,sp               ; Pop the TagList off the stack
  221.         tst.l   d0
  222.         bne.s   88$
  223.  
  224.         move.l  fs_Mem(a2),d0           ; Calculate the module end position
  225.         add.l   fs_FileSize(a2),d0
  226.         move.l  d0,fs_EndMem(a2)
  227.  
  228. 9$      moveq   #1,d0
  229. 99$     apop
  230.         rts
  231.  
  232. 88$     moveq   #XPKERR_IOERRIN,d1      ; See if it was a DOS error
  233.         cmp.l   d0,d1
  234.         beq     99$
  235.         moveq   #XPKERR_NOMEM,d1        ; See if it was not enough memory
  236.         cmp.l   d0,d1
  237.         beq     dienocmem
  238.         lea     xpkerrmsg(a4),a0        ; Use XPK's error message
  239.         bra     diemes
  240.  
  241. *** unloadfile - Unload a file (if loaded)
  242. * a0 = Pointer to filespec
  243. unloadfile:
  244.         move.l  fs_Mem(a0),a1
  245.         clr.l   fs_Mem(a0)
  246.         move.l  a1,d0
  247.         beq.s   9$
  248.         move.l  fs_AllocSize(a0),d0
  249.         move.l  a6,-(sp)
  250.         move.l  _SysBase(a4),a6
  251.         jsr     _LVOFreeMem(a6)
  252.         move.l  (sp)+,a6
  253. 9$      rts
  254.  
  255.  
  256.  
  257. *** findauthor - Find the author of the current song (into authorname)
  258. * a5 = Pointer to GMOD header
  259. findauthor:
  260.         moveq   #0,d0
  261.         move.l  cursong(a4),d1
  262.         movea.w #gmod_GetSongAuthor,a1
  263.         gmodmaycall a1
  264.         move.l  d0,authorname(a4)
  265.         bne.s   9$
  266.         lea     unknowntxt(a4),a0
  267.         move.l  a0,authorname(a4)
  268. 9$      rts
  269.  
  270. *** findcursong - Find the song to start playing, adjusting if necessary
  271. * Returns: d0 = Adjusted song number
  272. findcursong:
  273.         move.l  cursong(a4),d0          ; Check the "recommended" song number
  274.  
  275.         bpl.s   19$                     ; See if it's the user's option
  276.         cmp.b   #PM_RANDOM,_playmode(a4)
  277.         bne.s   15$
  278.         moveq   #0,d0                   ; FIXME: Select random song
  279.         bra.s   19$
  280. 15$     moveq   #0,d0
  281. 19$
  282.         cmp.l   numsongs(a4),d0         ; Make sure it's under the maximum
  283.         bcs.s   49$
  284.         moveq   #0,d0                   ; Always wrap around to song 0
  285. 49$
  286.         move.l  d0,cursong(a4)          ; Store it back into cursong
  287.  
  288.         rts
  289.  
  290. *** setsong - Start playing a different song in the current module
  291. * d0 = Song number to start playing
  292. _setsong
  293.         move.l  4(sp),d0
  294. setsong
  295.         move.l  numsongs(a4),d1         ; Make sure there are at least two songs
  296.         subq.l  #1,d1
  297.         beq.s   99$
  298.  
  299.         move.l  d0,cursong(a4)          ; Save new song number
  300.  
  301.         movem.l a5-a6,-(sp)
  302.         move.l  gmodptr(a4),a5
  303.         move.l  _SysBase(a4),a6
  304. *       DISABLE                         ; No interrupts while song is stopped
  305.  
  306.         moveq   #gmod_StopMusic,d0      ; Stop the current song
  307.         gmodmaycall d0
  308.  
  309.         bsr     findcursong             ; Find/adjust the song to play
  310.  
  311.         moveq   #gmod_StartMusic,d1     ; Start the new music
  312.         gmodmaycall d1
  313.  
  314.         clr.l   _songtime(a4)           ; Clear the song timer
  315.  
  316. 9$      bsr     findauthor              ; See who wrote this song
  317.  
  318. *       ENABLE
  319.         movem.l (sp)+,a5-a6
  320.  
  321. 99$     bset    #SB_WINDOWUP,_sysflags(a4)
  322.         rts
  323.  
  324. *** catalogsongs - Create a catalog of songs for the current module
  325. * a5 = GMOD pointer
  326. catalogsongs:
  327.         apush4
  328.  
  329.         lea     modremember(a4),a0      ; Allocate memory for catalog
  330.         move.l  numsongs(a4),d0
  331.         move.l  d0,d2
  332.         addq.l  #1,d0
  333.         lsl.l   #2,d0
  334.         bsr     allocmod
  335.         move.l  d0,songcatalog(a4)
  336.         beq     dienomem
  337.  
  338.         move.l  d0,a2                   ; Create the song list
  339.         movea.w #gmod_GetSongName,a6
  340.         moveq   #0,d3
  341. 11$     move.l  d3,d1
  342.         moveq   #0,d0
  343.         gmodmaycall a6
  344.         move.l  d0,(a2)+
  345.         bne.s   15$
  346.         lea     unknowntxt(a4),a0
  347.         move.l  a0,-4(a2)
  348. 15$     addq.l  #1,d3
  349.         subq.l  #1,d2
  350.         bne.s   11$
  351.         clr.l   (a2)
  352.  
  353.         apop4
  354.         rts
  355.  
  356.  
  357.  
  358. *** freemodfile - Free the modfile string
  359. freemodfile:
  360.         move.l  modfile(a4),d0
  361.         beq.s   9$
  362.         move.l  a6,-(sp)
  363.         move.l  d0,a1
  364.         move.l  modfilesize(a4),d0
  365.         move.l  _SysBase(a4),a6
  366.         jsr     _LVOFreeMem(a6)
  367.         clr.l   modfile(a4)
  368.         move.l  (sp)+,a6
  369. 9$      rts
  370.  
  371. *** setmodfile - Copy a filename into the modfile buffer
  372. * a0 = Pointer to filename to copy
  373. setmodfile:
  374.         movem.l a2/a6,-(sp)
  375.         move.l  a0,a2
  376.         bsr     freemodfile
  377.  
  378.         move.l  a2,a0                   ; Find the string length
  379.         moveq   #0,d0
  380. 1$      addq.l  #1,d0
  381.         tst.b   (a0)+
  382.         bne.s   1$
  383.         move.l  d0,modfilesize(a4)
  384.  
  385.         moveq   #0,d1                   ; Allocate the modfile buffer
  386.         move.l  _SysBase(a4),a6
  387.         jsr     _LVOAllocMem(a6)
  388.         move.l  d0,modfile(a4)
  389.         beq     dienomem
  390.  
  391.         move.l  d0,a0                   ; Copy the buffer
  392. 2$      move.b  (a2)+,(a0)+
  393.         bne.s   2$
  394.  
  395.         movem.l (sp)+,a2/a6
  396.         rts
  397.  
  398.  
  399. *** addinfopad - Add a pad line to the info list (only if the list is already started)
  400. addinfopad
  401.         tst.l   infolist(a4)
  402.         bz      addinfo_rts
  403.         lea     nulllab(a4),a0
  404.         ; Fall through...
  405. *** addinfo - Add a string to the info list (allocate a new info list if necessary)
  406. * a0 = Text
  407. addinfo
  408.         apush4
  409.         move.l  a0,a3
  410.         move.l  _IntuitionBase(a4),a6
  411.  
  412.         bsr     _infowindetach
  413.  
  414.         tst.l   infolist(a4)            ; Make sure we have a list to put things on
  415.         bnz.b   \gotlist
  416.         lea     modremember(a4),a0
  417.         moveq   #MLH_SIZE,d0
  418.         moveq   #0,d1
  419.         jl      AllocRemember
  420.         move.l  d0,infolist(a4)
  421.         bz      \out
  422.         move.l  d0,a1
  423.         NEWLIST a1
  424. \gotlist
  425.  
  426. \lloop
  427.         move.l  a3,a2
  428.         moveq   #-1,d2
  429. \loop
  430.         addq.w  #1,d2                   ; Search for a null in this line
  431.         move.b  (a3)+,d0
  432.         bz.b    \add
  433.         cmp.b   #10,d0
  434.         beq.b   \add
  435.         cmp.w   #INFOCOLS,d2
  436.         blo.b   \loop
  437.  
  438.         move.l  a3,a1                   ; Search backwards for a word break
  439.         move.w  d2,d1
  440. \bloop
  441.         subq.w  #1,d2
  442.         cmp.w   #INFOCOLS/2,d2          ; Fill at least half a line
  443.         beq.b   \lbreak
  444.         cmp.b   #' ',-(a3)
  445.         bne.b   \bloop
  446.         addq.w  #1,d2
  447.         addq    #1,a3
  448.         bra.b   \add
  449.  
  450. \lbreak
  451.         lea     -1(a1),a3               ; Break without regard to words
  452.         move.w  d1,d2
  453. \add
  454.         lea     modremember(a4),a0      ; Allocate a new info node
  455.         moveq   #LN_SIZE+1,d0
  456.         add.w   d2,d0
  457.         moveq   #0,d1
  458.         jl      AllocRemember
  459.         tst.l   d0
  460.         bz.b    \out
  461.  
  462.         move.l  d0,a1                   ; Add it to the list
  463.         move.l  infolist(a4),a0
  464.         ADDTAIL
  465.  
  466.         lea     LN_SIZE(a1),a1          ; Copy the string into it
  467.         move.l  a1,LN_NAME-LN_SIZE(a1)
  468.         bra.b   \copyin
  469. \copy
  470.         move.b  (a2)+,(a1)+
  471. \copyin
  472.         dbra    d2,\copy
  473.         clr.b   (a1)
  474.  
  475.         tst.b   -1(a3)                  ; Next line
  476.         bnz.b   \lloop
  477. \out
  478.         bsr     _infowinattach
  479.  
  480.         apop4
  481. addinfo_rts
  482.         rts
  483.  
  484.  
  485. *** ldmod - (Internal) - Load module used by loadmod and startmod
  486. * a0 = Pointer to filename
  487. * Returns: CCR, d0 = progload()+1, 0 if everything successful, dies on failure
  488. ldmod:
  489.         move.l  modfile(a4),a0          ; Find the filename to display
  490.         move.l  (a0),d0
  491.         bsr     toupperlong
  492.         cmpi.l  #'MOD.',d0
  493.         bne.s   19$
  494.         addq.l  #4,a0
  495. 19$     move.l  a0,modname(a4)
  496.  
  497.         lea     modspec(a4),a1          ; Load the module
  498.         move.l  modfile(a4),a0
  499.         bsr     loadfile
  500.         beq     dienofile
  501.  
  502.         move.l  modmem(a4),a0           ; See if this is a program
  503.         cmpi.l  #'PROG',(a0)
  504.         beq     \isprog
  505.  
  506.         ; FIXME: Load mod prefs
  507.  
  508.         move.l  modmem(a4),a0
  509.         pea     5$
  510.  
  511.         move.l  (a0),d0                 ; Modules IDable in first long
  512.         cmpi.l  #'GMOD',d0              ; General executable module
  513.         beq     gmodstart
  514.         cmpi.l  #'XMOD',d0              ; Executable module
  515.         beq     xmodstart
  516.         cmpi.l  #'AMOD',d0              ; Absolute executable module
  517.         beq     amodstart
  518.         cmpi.l  #'BeEp',d0              ; JamCracker module
  519.         beq     jamstart
  520.         cmpi.l  #'SMOD',d0              ; Future Composer old module
  521.         beq     fcostart
  522.         cmpi.l  #'FC14',d0              ; Future Composer 1.4 module
  523.         beq     fc14start
  524.         cmpi.l  #'OKTA',d0              ; Oktalyzer module
  525.         beq     oktastart
  526.         cmpi.l  #'MMD0',d0              ; MED 3.xx module
  527.         beq     medstart
  528.         cmpi.l  #'MMD1',d0              ; OctaMED Pro module
  529.         beq     medstart
  530.         cmpi.l  #'MMU2',d0              ; Digital Sound Studio module
  531.         beq     dssstart
  532.         cmpi.l  #$48e7f1fe,d0           ; Dave Whittaker module
  533.         beq     whitstart
  534.         cmpi.l  #$08f90001,d0           ; SidMon 2.1 module
  535.         beq     sid2start
  536.         cmpi.l  #$48e700f0,d0           ; Mark II module
  537.         beq     markiistart
  538.  
  539.         clr.b   d0                      ; Face The Music module
  540.         cmpi.l  #'FTM'<<8,d0
  541.         beq     ftmstart
  542.  
  543.         cmpi.l  #'8SVX',$8(a0)          ; 8SVX sounds (possibly sequenced)
  544.         beq     soundstart
  545.  
  546.         move.l  $1a(a0),d0              ; SoundMonitor module
  547.         clr.b   d0
  548.         cmpi.l  #'V.2'<<8,d0
  549.         beq     soundmonstart
  550.  
  551.         cmpi.l  #$4eaefeda,$80(a0)      ; SoundFX executable module
  552.         beq     fxstart
  553.  
  554.         cmpi.l  #'PATT',$1f6(a0)        ; NoiseTracker packed module
  555.         beq     ntpackstart
  556.  
  557.         move.l  $438(a0),d0             ; NoiseTrackerish module
  558.         cmpi.l  #'M.K.',d0
  559.         beq     ntststart
  560.         cmpi.l  #'FLT4',d0
  561.         beq     ntststart
  562.         cmpi.l  #'EXO4',d0
  563.         beq     ntststart
  564.  
  565.         cmpi.l  #'MTN'<<8,$5b8(a0)      ; SoundTracker 2.0-2.6 module
  566.         beq     ststart
  567.  
  568.         cmpi.l  #'TA1A',$51c(a0)        ; Delta Music module
  569.         beq     deltastart
  570.         cmpi.l  #'TA1A',$27c(a0)        ; Delta Music module
  571.         beq     delta2start
  572.  
  573.         cmpi.w  #$4efa,(a0)             ; Generic embedded module
  574.         beq     genembstart
  575.  
  576.         move.l  a0,a1                   ; NoisePacker module
  577.         move.w  (a1),d0
  578.         cmp.w   #$1c,d0
  579.         blo     \notnp
  580.         lea     -4(a1,d0.w),a2
  581.         tst.l   (a1)+
  582.         bz      \notnp
  583.         tst.l   (a1)+
  584.         bz      \notnp
  585. \nptest
  586.         cmp.l   a2,a1
  587.         bhs     npstart
  588.         tst.l   (a1)+
  589.         bnz     \notnp
  590.         tst.l   (a1)+
  591.         bnz     \nptest
  592. \notnp
  593.  
  594.         moveq   #$60,d1                 ; ST/NT module
  595.         move.b  (a0),d0                 ; FIXME: Need better detection here
  596.         and.b   d1,d0
  597.         beq.s   51$
  598.         move.b  $13(a0),d0
  599.         and.b   d1,d0
  600.         beq     ntstart
  601.  
  602. 51$     bra     dieunkmod               ; Doesn't match anything we know of
  603.  
  604. 5$      move.l  d0,gmodptr(a4)          ; Save the GMOD header pointer
  605.         move.l  d0,a5
  606.  
  607.         moveq   #gmod_NotePlayer,d1     ; Give the module our NotePlayer
  608.         moveq   #0,d0
  609.         lea     NoteSys,a0
  610.         gmodmaycall d1
  611.         tst.l   d0
  612.         sne     portablemodule(a4)
  613.  
  614.         moveq   #gmod_InitMusic,d1      ; Call the initialization vector
  615.         moveq   #0,d0
  616.         gmodmaycall d1
  617.         tst.l   d0
  618.         beq.s   39$
  619.         move.l  d0,a0
  620.         bra     diemes
  621. 39$
  622.         moveq   #gmod_GetNumSongs,d1    ; Find the number of songs
  623.         moveq   #0,d0
  624.         gmodmaycall d1
  625.         tst.l   d0
  626.         bne.s   7$
  627.         moveq   #1,d0
  628. 7$      move.l  d0,numsongs(a4)
  629.  
  630.         moveq   #gmod_GetMakerName,d1   ; Find the module type
  631.         moveq   #0,d0
  632.         gmodmaycall d1
  633.         move.l  d0,modtypename(a4)
  634.         bne.s   61$
  635.         lea     gmodname(a4),a0
  636.         move.l  a0,modtypename(a4)
  637. 61$
  638.         bsr     catalogsongs            ; Catalog the songs in the module
  639.  
  640.         bsr     findauthor              ; See who wrote this song
  641.  
  642.         moveq   #0,d0                   ; Put the scrolltext into the info window
  643.         moveq   #gmod_GetScroll,d1
  644.         gmodmaycall d1
  645.         tst.l   d0
  646.         bz.b    \noscroll
  647.         move.l  d0,-(sp)
  648.         bsr     addinfopad
  649.         move.l  (sp)+,a0
  650.         bsr     addinfo
  651. \noscroll
  652.  
  653.         moveq   #gmod_Hook,d7           ; Give the module our Hook
  654.         lea     playerhook(a4),a0
  655.         move.l  #GMODHF_REPEAT!GMODHF_SEQUENCE,d1
  656.         moveq   #0,d0
  657.         gmodmaycall d7
  658.         btst    #GMODHB_SEQUENCE,d0
  659.         bz.s    \nohookseq
  660.         bset    #MTB_SEQUENCE,modtype(a4)
  661. \nohookseq:
  662.         btst    #GMODHB_REPEAT,d0
  663.         bz.s    \nohookrepeat
  664.         bset    #MTB_REPEAT,modtype(a4)
  665. \nohookrepeat:
  666.  
  667.         btst.b  #MTB_FILTER,modtype(a4)         ; See if we can control the filter
  668.         bnz.b   \hasfilt
  669.         lea     filter(a4),a0
  670.         sub.l   a1,a1
  671.         moveq   #-1,d0
  672.         bsr     GlobSetByte
  673. \hasfilt
  674.  
  675.         btst.b  #MTB_PROTRACKER,modtype(a4)     ; See if it's the Protracker player
  676.         bnz.b   \ispt
  677.         lea     modflags(a4),a0
  678.         move.b  (a0),d0
  679.         bset.b  #MNB_NOTPROTRACKER,d0
  680.         bnz.b   \ispt
  681.         sub.l   a1,a1
  682.         bsr     GlobSetByte
  683. \ispt
  684.  
  685.         btst    #MTB_SEQUENCE,modtype(a4)       ; See if the player can jump around
  686.         bz.b    \nojump
  687.         moveq   #gmod_Jump,d0
  688.         bsr     gmodcheck
  689.         bz.b    \nojump
  690.         bset.b  #MTB_JUMP,modtype(a4)
  691. \nojump
  692.  
  693.         moveq   #0,d0
  694.         rts
  695.  
  696. \isprog:                                ; We found a module program!
  697.         clr.l   -(sp)                   ; Load the program
  698.         move.l  modfile(a4),-(sp)
  699.         clr.l   -(sp)
  700.         bsr     _progload
  701.         lea     12(sp),sp
  702.         move.l  d0,d2
  703.         bsr     endmod                  ; Unload what we loaded
  704.         move.l  d2,d0
  705.         addq.l  #1,d0
  706.         rts
  707.  
  708. *** plmod - (Internal) - Play module used by playmod and startmod
  709. * d0 = 0 to start, 1 to continue
  710. * Returns 0 if successful, 1 if couldn't continue, dies on other errors
  711. plmod:
  712.         move.l  d0,d7                   ; Save start/continue flag
  713.  
  714.         tst.b   _playing(a4)            ; Don't restart if already playing
  715.         bne     9$
  716.  
  717.         move.l  gmodptr(a4),d0          ; Make sure a module is loaded
  718.         beq     dienotloaded
  719.         move.l  d0,a5
  720.  
  721.         move.b  noaudalloc(a4),d0
  722.         or.b    portablemodule(a4),d0
  723.         bnz     \noalloc
  724.         bsr     allocaudio              ; Allocate the audio.device
  725. \noalloc
  726.  
  727.         tst.l   d7                      ; Start or continue?
  728.         bne.s   15$
  729.  
  730.         move.l  _SysBase(a4),a1         ; Find the clock frequency
  731.         move.l  #715909,d0
  732.         cmp.b   #50,PowerSupplyFrequency(a1)
  733.         bne.s   \ntsc
  734.         move.l  #709379,d0
  735. \ntsc   move.l  d0,clockfreq(a4)
  736.  
  737.         bsr     findcursong             ; Find the song to start playing
  738.  
  739.         moveq   #gmod_StartMusic,d1     ; Start playing the music
  740.         move.l  modmem(a4),a0           ; Convenience for built-in players
  741.         gmodmaycall d1
  742.  
  743.         clr.l   _songtime(a4)           ; Clear the song timer
  744.  
  745.         bclr.b  #SB_REPEAT,_sysflags(a4) ; Kill any stray repeat flags
  746.  
  747.         bra.s   19$
  748. 15$
  749.         moveq   #gmod_ContinueMusic,d1  ; Try to continue the music
  750.         moveq   #0,d0
  751.         gmodmaycall d1
  752.         tst.l   d0
  753.         beq     7$
  754. 19$
  755.         tst.b   portablemodule(a4)      ; Set the module's master volume
  756.         bnz     \hasvol
  757.         moveq   #gmod_SetVolume,d0
  758.         bsr     gmodcheck
  759.         bz.b    \novol
  760. \hasvol
  761.         st.b    _playing(a4)
  762.         bsr     playervolume
  763.         clr.b   _playing(a4)
  764.         bra.b   \finvol
  765. \novol
  766.         lea     volume(a4),a0           ; Disable the volume control
  767.         sub.l   a1,a1
  768.         moveq   #-1,d0
  769.         bsr     GlobSetWord
  770. \finvol
  771.  
  772.         lea     audisave(a4),a3         ; Set the audio channel interrupts
  773.         lea     audints(a4),a2
  774.         moveq   #gmod_Audio0,d2
  775.         moveq   #INTB_AUD0,d3
  776.         move.w  #INTF_SETCLR,d4
  777.         bsr     88$
  778.         bsr     88$
  779.         bsr     88$
  780.         bsr     88$
  781.         move.w  d4,CUSTOM+intena
  782.  
  783.         moveq   #gmod_VBlank50,d0       ; Set the timing interrupt
  784.         bsr     gmodcheck
  785.         beq.s   21$
  786.         moveq   #50,d0
  787.         lea     gmod_VBlank50(a5),a0
  788.         bra.s   28$
  789. 21$     moveq   #gmod_VBlank60,d0
  790.         bsr     gmodcheck
  791.         beq.s   22$
  792.         moveq   #60,d0
  793.         lea     gmod_VBlank60(a5),a0
  794.         bra.s   28$
  795. 22$     moveq   #gmod_TimerTick,d0
  796.         bsr     gmodcheck
  797.         beq.s   29$
  798.         moveq   #0,d0
  799.         jsr     gmod_GetFrequency(a5)
  800.         tst.l   d0
  801.         beq.s   29$
  802.         bpl.s   27$                     ; Convenience for internal players
  803.         moveq   #50,d0
  804.         bset    #MTB_MODSPEED,modtype(a4)
  805. 27$     lea     gmod_TimerTick(a5),a0
  806. 28$     move.l  modmem(a4),a1           ; a1 = module pointer (for our players)
  807.         bsr     settint
  808.         bra.b   \speeddone
  809. 29$
  810.         lea     speed(a4),a0            ; No speed control - disable the speed gadget
  811.         sub.l   a1,a1
  812.         moveq   #0,d0
  813.         bsr     GlobSetWord
  814. \speeddone
  815.  
  816.         cmp.b   #2,filter(a4)           ; Set the filter
  817.         bne.b   \filtoff
  818. \filton
  819.         bclr.b  #CIAB_LED,CIAA+ciapra
  820.         bra.b   \filtdone
  821. \filtoff
  822.         bset.b  #CIAB_LED,CIAA+ciapra
  823. \filtdone
  824.  
  825.         st.b    _playing(a4)            ; Set playing flag
  826. 9$      moveq   #0,d0                   ; Return success code
  827.         rts
  828.  
  829. 88$     move.l  a2,a1
  830.         move.l  d2,d0
  831.         bsr     gmodcheck
  832.         beq.s   89$
  833.         move.b  #NT_INTERRUPT,LN_TYPE(a1)       ; Set the interrupt vector
  834.         lea     audiointname(a4),a0
  835.         move.l  a0,LN_NAME(a1)
  836.         lea     0(a5,d2.w),a0
  837.         move.l  a0,IS_CODE(a1)
  838.         move.l  a4,IS_DATA(a1)
  839.         move.l  d3,d0
  840.         move.l  _SysBase(a4),a6
  841.         jsr     _LVOSetIntVector(a6)
  842.         move.l  d0,(a3)
  843.         bset    d3,d4                   ; Turn on the interrupt later
  844. 89$     addq.l  #4,d2
  845.         addq.l  #4,a3
  846.         addq.l  #1,d3
  847.         adda.w  #IS_SIZE,a2
  848.         rts
  849.  
  850. 7$      bsr     stpmod                  ; Stop whatever was started
  851.  
  852.         moveq   #1,d0                   ; Return can't continue error code
  853.         rts
  854.  
  855. *** stpmod - (Internal) - Stop a playing module
  856. stpmod:
  857.         tst.b   _playing(a4)            ; Turn the LED back on
  858.         bz.b    \noled
  859.         bclr.b  #CIAB_LED,CIAA+ciapra
  860. \noled
  861.  
  862.         clr.b   _playing(a4)            ; Clear the playing flag
  863.  
  864.         bsr     stoptint                ; Stop timer interrupts
  865.  
  866.         lea     audisave(a4),a2         ; Stop audio channel interrupts
  867.         moveq   #INTB_AUD0,d2
  868.         move.w  #INTF_AUD0!INTF_AUD1!INTF_AUD2!INTF_AUD3,CUSTOM+intena
  869.         move.w  #INTF_AUD0!INTF_AUD1!INTF_AUD2!INTF_AUD3,CUSTOM+intreq
  870.         bsr.s   88$
  871.         bsr.s   88$
  872.         bsr.s   88$
  873.         bsr.s   88$
  874.         bra.s   85$
  875. 88$     move.l  d2,d0
  876.         addq.l  #1,d2
  877.         move.l  (a2)+,d1
  878.         beq.s   89$
  879.         clr.l   -4(a2)
  880.         move.l  d1,a1
  881.         move.l  _SysBase(a4),a6
  882.         jmp     _LVOSetIntVector(a6)
  883. 89$     rts
  884. 85$
  885.         move.l  gmodptr(a4),d0          ; Stop playing the music
  886.         beq.s   29$
  887.         move.l  d0,a5
  888.         moveq   #gmod_StopMusic,d0
  889.         gmodmaycall d0
  890. 29$
  891.         bsr     clearflash
  892.  
  893.         bra     freeaudio               ; Free the audio channels
  894.  
  895.  
  896. *** loadmod - Load a module without playing it
  897. * a0 = Pointer to filename
  898. * Returns: d0 = Null if successful, pointer to error message if failed
  899. _loadmod
  900.         move.l  4(sp),a0
  901. loadmod
  902.         movem.l d2-d7/a2-a6,-(sp)
  903.         move.l  a0,a2
  904.  
  905.         bsr     endmod                  ; First make sure nothing is playing
  906.  
  907.         move.l  sp,stackpt(a4)          ; Save the stack pointer in case we die
  908.  
  909.         move.l  a2,a0                   ; Set/allocate the modfile string
  910.         bsr     setmodfile
  911.  
  912.         bsr     ldmod                   ; Load the module
  913.         bz.s    9$
  914.         subq.l  #1,d0                   ; Find the real return code
  915.  
  916. 9$      bset    #SB_WINDOWUP,_sysflags(a4)
  917.         movem.l (sp)+,d2-d7/a2-a6
  918.         rts
  919.  
  920.  
  921. *** playmod - Play an already-loaded module
  922. * d0 = Song number (-1 = user's choice)
  923. * Returns: d0 = Null if successful, pointer to error message if failed
  924. _playmod
  925.         move.l  4(sp),d0
  926. playmod
  927.         movem.l d2-d7/a2-a6,-(sp)
  928.         tst.l   d0                      ; Only change songs if it's specified
  929.         bmi.s   1$
  930.         move.l  d0,cursong(a4)          ; Save the song number
  931. 1$
  932.         bsr     stpmod                  ; Stop any previously playing song
  933.  
  934.         move.l  sp,stackpt(a4)          ; Save the stack pointer in case we die
  935.  
  936.         moveq   #0,d0                   ; Start playing the module
  937.         bsr     plmod
  938.  
  939.         bset    #SB_WINDOWUP,_sysflags(a4)
  940.  
  941.         moveq   #0,d0                   ; Return a success code
  942.         movem.l (sp)+,d2-d7/a2-a6
  943.         rts
  944.  
  945. *** startmod - Load a module and start it playing
  946. * a0 = Pointer to filename
  947. * d0 = Song number (-1 = user's choice)
  948. * Returns: d0 = Null if successful, pointer to error message if failed
  949. _startmod
  950.         move.l  4(sp),a0
  951.         move.l  8(sp),d0
  952. startmod
  953.         movem.l d2-d7/a2-a6,-(sp)
  954.         move.l  d0,cursong(a4)          ; Save the song number
  955.         move.l  a0,a2
  956.  
  957.         bsr     endmod                  ; First make sure nothing is playing
  958.  
  959.         move.l  sp,stackpt(a4)          ; Save the stack pointer in case we die
  960.  
  961.         move.l  a2,a0                   ; Set/allocate the modfile string
  962.         bsr     setmodfile
  963.  
  964.         bsr     ldmod                   ; Load the module
  965.         bz.s    5$
  966.         subq.l  #1,d0
  967.         bnz.s   9$
  968.         move.l  d0,-(sp)
  969.         move.l  a0,-(sp)
  970.         bsr     _progstart              ; Start the program too
  971.         addq    #8,sp
  972.         bra.s   9$
  973.  
  974. 5$      moveq   #0,d0                   ; Play the module
  975.         bsr     plmod
  976.  
  977.         moveq   #0,d0
  978. 9$      bset    #SB_WINDOWUP,_sysflags(a4)
  979.         movem.l (sp)+,d2-d7/a2-a6
  980.         rts
  981.  
  982. *** contmod - Continue a module from where it left off
  983. * Returns: d0 = Null if successful, error message if failed
  984. contmod
  985. _contmod
  986.         tst.b   _playing(a4)            ; See if it's already playing
  987.         bne.s   99$
  988.  
  989.         movem.l d2-d7/a2-a6,-(sp)
  990.         move.l  sp,stackpt(a4)          ; Save the stack pointer in case we die
  991.  
  992.         moveq   #1,d0                   ; Continue the module
  993.         bsr     plmod
  994.         beq.s   19$
  995.         lea     nocontinue(a4),a0       ; Can't continue - error message
  996.         move.l  a0,d0
  997. 19$
  998.         movem.l (sp)+,d2-d7/a2-a6
  999.         rts
  1000.  
  1001.         bset    #SB_WINDOWUP,_sysflags(a4)
  1002.  
  1003. 99$     moveq   #0,d0                   ; Return a success code immediately
  1004.         rts
  1005.  
  1006. *** contplaymod - Continue current module if possible, otherwise restart it
  1007. * Returns: d0 = Null if successful, error message if failed
  1008. contplaymod:
  1009. _contplaymod:
  1010.         bsr     contmod
  1011.         lea     nocontinue(a4),a0
  1012.         cmp.l   a0,d0
  1013.         bne.s   9$
  1014.         moveq   #-1,d0
  1015.         bsr     playmod
  1016. 9$      rts
  1017.  
  1018. *** stopmod - Stop a playing module
  1019. * Returns: d0 = NULL
  1020. stopmod:
  1021. _stopmod:
  1022.         movem.l d2-d7/a2-a6,-(sp)       ; Stop the module
  1023.         bsr     stpmod
  1024.         movem.l (sp)+,d2-d7/a2-a6
  1025.  
  1026.         bset    #SB_WINDOWUP,_sysflags(a4)
  1027.  
  1028.         moveq   #0,d0
  1029.         rts
  1030.  
  1031. *** endmod - Stop and unload a module
  1032. * Returns: d0 = NULL
  1033. endmod:
  1034. _endmod:
  1035.         movem.l d2-d7/a2-a6,-(sp)
  1036.         move.l  sp,stackpt(a4)
  1037.         moveq   #0,d3
  1038.         bra.s   die
  1039.  
  1040. *** die - and other forms of death (from the module player only)
  1041. dienotloaded:                           ; No module loaded
  1042.         lea     notloaded(a4),a0
  1043.         bra.s   diemes
  1044. diedontcompress:                        ; Reloaded compressed module
  1045.         lea     dontcompress(a4),a0
  1046.         bra.s   diemes
  1047. dienofile:                              ; File not found
  1048.         lea     nofile(a4),a0
  1049.         bra.s   diemes
  1050. dieunkmod:                              ; File is not a module
  1051.         lea     unkmod(a4),a0
  1052.         bra.s   diemes
  1053. diecorrupt:                             ; Module is corrupt
  1054.         lea     cormod(a4),a0
  1055.         bra.s   diemes
  1056. dieerrplay:                             ; Error playing module
  1057.         lea     errplay(a4),a0
  1058.         bra.s   diemes
  1059. dienoabs:
  1060.         lea     noabs(a4),a0            ; Couldn't allocate absolute memory
  1061.         bra.s   diemes
  1062. dienotimer:
  1063.         lea     notimer(a4),a0          ; Couldn't allocate either CIAB timer
  1064.         bra.s   diemes
  1065. dienocmem:                              ; Not enough memory
  1066.         lea     nocmem(a4),a0
  1067.         bra.s   diemes
  1068. dienomem:                               ; Not enough memory
  1069.         lea     nomemtext(a4),a0
  1070. diemes:
  1071.         move.l  a0,d3
  1072. die:
  1073.         bsr     stpmod                  ; Stop playing the module
  1074.  
  1075.         move.l  gmodptr(a4),d0          ; Prepare to unload
  1076.         beq.s   29$
  1077.         move.l  d0,a5
  1078.         moveq   #gmod_EndMusic,d0
  1079.         gmodmaycall d0
  1080.         clr.l   gmodptr(a4)
  1081. 29$
  1082.         clr.l   songcatalog(a4)         ; Erase all pointers to memory we are about to free
  1083.         clr.l   infolist(a4)
  1084.  
  1085.         bsr     _infowinattach          ; Clear out the info window
  1086.  
  1087.         lea     modremember(a4),a0      ; Free any miscellaneous memory we allocated for the module
  1088.         moveq   #1,d0
  1089.         move.l  _IntuitionBase(a4),a6
  1090.         jl      FreeRemember
  1091.  
  1092.         bsr     closeloadhan            ; Close any handle we were trying to load with
  1093.  
  1094.         lea     modspec(a4),a0          ; Free the module memory
  1095.         bsr     unloadfile
  1096.  
  1097.         lea     suppspec(a4),a0         ; Free any secondary data file
  1098.         bsr     unloadfile
  1099.  
  1100.         moveq   #1,d0                   ; Default to one song
  1101.         move.l  d0,numsongs(a4)
  1102.         clr.l   cursong(a4)
  1103.  
  1104.         clr.b   modtype(a4)             ; Default no special module type
  1105.  
  1106.         clr.l   authorname(a4)          ; Control-panel text fields
  1107.         clr.l   modtypename(a4)
  1108.         clr.l   modname(a4)
  1109.  
  1110.         clr.l   ntauthor(a4)
  1111.  
  1112.         clr.b   noaudalloc(a4)
  1113.  
  1114.         moveq   #-1,d0
  1115.         move.l  d0,_songlen(a4)
  1116.  
  1117.         move.w  d0,_fadevol(a4)
  1118.  
  1119.         bset    #SB_WINDOWUP,_sysflags(a4)
  1120.  
  1121.         bsr     freemodfile             ; Free the modfile buffer
  1122.  
  1123.         move.l  stackpt(a4),sp          ; Return to caller
  1124.         move.l  d3,d0
  1125.         movem.l (sp)+,d2-d7/a2-a6
  1126.         rts
  1127.  
  1128.  
  1129. *** moveabs - Move the module to an absolute position in memory (reload if necessary)
  1130. * a0 = Position to move module to
  1131. * Returns: a0 = New module position
  1132. moveabs:
  1133.         apush4
  1134.  
  1135.         move.l  modsize(a4),d0          ; Allocate the required memory
  1136.         move.l  d0,d2
  1137.         move.l  a0,a1
  1138.         move.l  a0,a2
  1139.         move.l  _SysBase(a4),a6
  1140.         jl      AllocAbs
  1141.         tst.l   d0
  1142.         bz.b    1$
  1143.  
  1144.         move.l  modmem(a4),a0           ; Copy the module to the final location
  1145.         move.l  a2,a1
  1146.         move.l  d2,d0
  1147.         jl      CopyMem
  1148.  
  1149.         move.l  modmem(a4),a1           ; Free the old memory block
  1150.         move.l  modalloc(a4),d0
  1151.         jl      FreeMem
  1152.  
  1153.         move.l  a2,modmem(a4)           ; Point to the new block
  1154.         move.l  d2,modalloc(a4)
  1155.         add.l   d2,a2
  1156.         move.l  a2,modend(a4)
  1157.  
  1158.         bra     9$
  1159.  
  1160. 1$      move.l  modmem(a4),a1           ; First free the old block
  1161.         move.l  modalloc(a4),d0
  1162.         jl      FreeMem
  1163.         clr.l   modmem(a4)
  1164.  
  1165.         move.l  a2,a1                   ; Now see if we can allocate the memory
  1166.         move.l  d2,d0
  1167.         jl      AllocAbs
  1168.         tst.l   d0
  1169.         bz      dienoabs
  1170.  
  1171.         move.l  a2,modmem(a4)           ; Point to the new memory block
  1172.         move.l  d2,modalloc(a4)
  1173.         add.l   d2,a2
  1174.         move.l  a2,modend(a4)
  1175.  
  1176.         lea     modspec(a4),a1          ; Re-load the file at the required address
  1177.         move.l  modfile(a4),a0
  1178.         bsr     loadfile
  1179.         beq     dienofile
  1180.  
  1181. 9$      move.l  modmem(a4),a0
  1182.         apop4
  1183.         rts
  1184.  
  1185.  
  1186. *** hookfunc - Hook function called by modules
  1187. * a1 = Parameter packet
  1188. hookfunc:
  1189.         move.l  (a1)+,d0
  1190.         cmpi.l  #GMODHF_SEQUENCE,d0
  1191.         beq.s   \sequence
  1192.         cmpi.l  #GMODHF_REPEAT,d0
  1193.         beq     intrepeat
  1194.         moveq   #0,d0
  1195.         rts
  1196.  
  1197. \sequence:
  1198.         move.l  (a1)+,d0
  1199.         move.l  (a1)+,d1
  1200.         bra     intsongpos
  1201.  
  1202.  
  1203. *** getfreqmodspeed - Get the default module speed and set the MODSPEED flag
  1204. getfreqmodspeed:
  1205.         moveq   #50,d0
  1206.         bset    #MTB_MODSPEED,modtype(a4)
  1207.         rts
  1208.  
  1209.  
  1210. *** parseauthor - Find the author name in a string which potentially contains one
  1211. * a0 = Pointer to string
  1212. * Returns:
  1213. * a0 = Pointer to beginning of author name or NULL if none found
  1214. * a1 = Pointer to first character relating to the author name (<= a0)
  1215. parseauthor:
  1216.         move.l  a0,a1
  1217.         bra.s   11$                     ; Search for 'by' keyword
  1218. 1$      move.l  a0,a1
  1219.         move.b  (a0)+,d0
  1220.         bz.s    9$
  1221.         cmp.b   #$a9,d0                 ; Check for "©"
  1222.         beq     99$
  1223.         bsr     isalpha
  1224.         bnz.s   1$
  1225. 11$     move.b  (a0),d0
  1226.         bsr     toupper
  1227.         cmp.b   #'C',d0                 ; Check for "(C)"
  1228.         bne.s   12$
  1229.         cmp.b   #'(',-1(a0)
  1230.         bne.s   12$
  1231.         cmp.b   #')',1(a0)
  1232.         beq.s   92$
  1233. 12$     cmp.b   #'B',d0                 ; Check for "BY"
  1234.         bne.s   1$
  1235.         move.b  1(a0),d0
  1236.         bsr     toupper
  1237.         cmp.b   #'Y',d0
  1238.         bne.s   1$
  1239.         move.b  2(a0),d0
  1240.         bsr     isalpha
  1241.         bnz.s   1$
  1242. 92$     addq.l  #2,a0
  1243. 99$     rts
  1244.  
  1245. 9$      sub.l   a0,a0                   ; Return null for both strings
  1246.         move.w  a0,a1
  1247.         rts
  1248.  
  1249. *** prepstring - Prepare author/song name string for display - chop puctuation, etc.
  1250. * a0 = String to prepare
  1251. * Returns:
  1252. * a0 = New pointer to string
  1253. prepstring:
  1254.         move.l  a2,-(sp)
  1255.  
  1256.         bsr     stripblanks             ; Strip leading and trailing blanks
  1257.         bz.s    9$
  1258.  
  1259.         move.l  a0,a1                   ; Hunt down and eliminate EdPlayer junk
  1260. 1$      move.b  (a1)+,d0
  1261.         bz.s    19$
  1262.         cmp.b   #'`',d0
  1263.         bne.s   1$
  1264.         lea     -1(a1),a2
  1265.         move.l  a2,-(sp)
  1266.         cmp.b   #'`',(a1)+
  1267.         bne.s   13$
  1268.         subq.l  #1,a1
  1269.         addq.l  #1,(sp)
  1270. 13$     move.b  (a1)+,(a2)+
  1271.         bne.s   13$
  1272.         move.l  (sp)+,a1
  1273.         bra.s   1$
  1274. 19$
  1275.         subq.l  #1,a1                   ; Eliminate some punctuation at the end
  1276. 21$     cmp.l   a0,a1
  1277.         beq.s   \empty
  1278.         cmp.b   #'.',-(a1)
  1279.         beq.s   25$
  1280.         cmp.b   #',',(a1)
  1281.         bne.s   29$
  1282. 25$     clr.b   (a1)
  1283.         bra.s   21$
  1284. 29$
  1285. 9$      move.l  (sp)+,a2
  1286.         rts
  1287. \empty:
  1288.         sub.l   a0,a0
  1289.         bra.s   9$
  1290.  
  1291.  
  1292. *** ntgetsongname - Get song name (and possibly author) from a NoiseTracker module
  1293. ntgetsongname:
  1294.         move.l  modmem(a4),a0           ; See if the author's name is in the title
  1295.         bsr     parseauthor
  1296.         move.l  a0,d0
  1297.         bz.s    9$
  1298.  
  1299.         clr.b   (a1)                    ; Separate it from the title
  1300.         bsr     prepstring
  1301.         move.l  a0,ntauthor(a4)
  1302.  
  1303. 9$      move.l  modmem(a4),a0           ; Return the title
  1304.         bsr     prepstring
  1305.         move.l  a0,d0
  1306.         rts
  1307.  
  1308. *** ntgetsongauthor - Get author name from a NoiseTracker module
  1309. ntgetsongauthor:
  1310.         movem.l a2-a3,-(sp)
  1311.  
  1312.         move.l  ntauthor(a4),d0         ; See if we already found the author
  1313.         bnz     9$
  1314.  
  1315.         bsr     addinfopad              ; Display the instrument list verbatim
  1316.         move.l  modmem(a4),a0
  1317.         lea     20(a0),a2
  1318.         lea     31*30(a2),a3
  1319. \info
  1320.         tst.b   (a2)
  1321.         bz.b    \noinfo
  1322.         move.l  a2,a0
  1323.         bsr     addinfo
  1324. \noinfo
  1325.         lea     30(a2),a2
  1326.         cmp.l   a3,a2
  1327.         bne.b   \info
  1328.  
  1329.         move.l  modmem(a4),a0           ; Find an entry with author keywords
  1330.         lea     20(a0),a2
  1331.         lea     31*30(a2),a3
  1332. 1$      move.l  a2,a0
  1333.         bsr     parseauthor
  1334.         move.l  a0,d0
  1335.         bnz.s   2$
  1336.         lea     30(a2),a2
  1337.         cmp.l   a3,a2
  1338.         bne.s   1$
  1339.  
  1340.         move.l  modmem(a4),a0           ; Find an IntuiTracker scroll line
  1341.         lea     20(a0),a0
  1342.         lea     31*30(a0),a3
  1343. 3$      cmp.b   #'#',(a0)+
  1344.         beq.s   4$
  1345.         lea     30-1(a0),a0
  1346.         cmp.l   a3,a0
  1347.         bne.s   3$
  1348.  
  1349.         moveq   #0,d0                   ; Nothing found at all
  1350.         bra.s   9$
  1351.  
  1352. 2$      bsr     prepstring              ; Strip leading and trailing blanks
  1353.         move.l  a0,d0
  1354.         bnz.s   9$
  1355.  
  1356.         lea     30(a2),a0               ; Nothing on that line - use the next line
  1357.         cmp.b   #'#',(a0)               ; Skip leading IntuiTracker junk
  1358.         bne.s   4$
  1359.         addq.l  #1,a0
  1360.         cmp.b   #'#',(a0)               ; If there are *two*, it's probably decoration
  1361.         bne.s   4$
  1362.         subq.l  #1,a0
  1363. 4$      bsr     prepstring
  1364.         move.l  a0,d0
  1365.  
  1366. 9$      movem.l (sp)+,a2-a3
  1367.         rts
  1368.  
  1369.  
  1370. *** gmodstart - Code for general modules (GMOD's)
  1371. gmodstart:
  1372.         move.l  gmod_LoadAddress(a0),d1         ; Move the module if necessary
  1373.         beq.s   19$
  1374.         move.l  d1,a0
  1375.         bsr     moveabs
  1376. 19$     move.l  a0,d0
  1377.         move.l  gmod_Maker(a0),gmodnametype(a4) ; Find the module's maker ID
  1378.         rts
  1379.  
  1380. *** amodstart - Code for Absolute Executable modules (AMOD's)
  1381. amodloc equ     $10
  1382.  
  1383. amodstart:
  1384.         move.l  amodloc(a0),a0          ; Move to the required position
  1385.         bsr     moveabs
  1386.         ; Fall through and execute like an XMOD...
  1387. *** xmodstart - Code for Executable modules (XMOD's)
  1388. xminitentry     equ     $4
  1389. xmvbentry       equ     $8
  1390. xmendentry      equ     $c
  1391.  
  1392. xmodstart:
  1393.         plstartret 9$
  1394.  
  1395.         cnop    0,4
  1396.         dc.l    gmod_Hook
  1397. 9$      gmodnop
  1398.         gmodbra 2$                      ; StartMusic
  1399.         gmodbra 3$                      ; StopMusic
  1400.         gmodnop
  1401.         gmodnop
  1402.         gmodnop
  1403.         gmodnop
  1404.         gmodnop
  1405.         gmodnop
  1406.         gmodnop
  1407.         gmodnop
  1408.         gmodnop
  1409.         gmodnop
  1410.         gmodnop
  1411.         gmodnop
  1412.         gmodbra getfreqmodspeed         ; GetFrequency
  1413.         jmp     xmvbentry(a1)           ; TimerTick
  1414.         lea     xmodname(a4),a0         ; GetMakerName
  1415.         move.l  a0,d0
  1416.         rts
  1417.  
  1418. 2$      move.l  modmem(a4),a0
  1419.         jmp     xminitentry(a0)
  1420.  
  1421. 3$      move.l  modmem(a4),a0
  1422.         jmp     xmendentry(a0)
  1423.  
  1424. *** ntstart - Code to differentiate between ST/NT/PT and StarTrekker
  1425. ntststart:
  1426.         move.l  modfile(a4),a0          ; Check for a StarTrekker ".NT" file
  1427.         move.l  sp,a2
  1428.         moveq   #4,d0
  1429. 11$     addq.l  #1,d0
  1430.         tst.b   (a0)+
  1431.         bne.s   11$
  1432.         bclr    #0,d0
  1433.         sub.l   d0,sp
  1434.         move.l  sp,a1
  1435.         move.l  modfile(a4),a0
  1436.         bra.s   13$
  1437. 12$     move.b  d0,(a1)+
  1438. 13$     move.b  (a0)+,d0
  1439.         bne.s   12$
  1440.         move.b  #'.',(a1)+
  1441.         move.b  #'N',(a1)+
  1442.         move.b  #'T',(a1)+
  1443.         clr.b   (a1)
  1444.         move.l  sp,a0
  1445.         lea     suppspec(a4),a1
  1446.         bsr     loadfile
  1447.         move.l  a2,sp
  1448.         bnz     trekstart               ; Go to appropriate startup
  1449.         bra     ntstart
  1450.  
  1451. *** genembstart - Code for generic embedded-player modules (such as NoiseTracker packed w/player)
  1452. genembstart:
  1453.         cmpi.w  #$4efa,4(a0)            ; Make sure the other two JMP's exist
  1454.         bne     diecorrupt
  1455.         cmpi.w  #$4efa,8(a0)
  1456.         bne     diecorrupt
  1457.  
  1458.         plstartret 9$
  1459.  
  1460.         cnop    0,4
  1461.         dc.l    gmod_Hook
  1462. 9$      gmodnop
  1463.         gmodbra 2$                      ; StartMusic
  1464.         gmodbra 3$                      ; StopMusic
  1465.         gmodnop
  1466.         gmodnop
  1467.         gmodnop
  1468.         gmodnop
  1469.         gmodnop
  1470.         gmodnop
  1471.         gmodnop
  1472.         gmodnop
  1473.         gmodnop
  1474.         gmodnop
  1475.         gmodnop
  1476.         gmodnop
  1477.         gmodbra getfreqmodspeed         ; GetFrequency
  1478.         gmodbra 5$                      ; TimerTick
  1479.         lea     genembname(a4),a0       ; GetMakerName
  1480.         move.l  a0,d0
  1481.         rts
  1482.  
  1483. 2$      movem.l d2-d7/a2-a6,-(sp)
  1484.         moveq   #0,d0
  1485.         move.l  modmem(a4),a5
  1486.         jsr     (a5)
  1487.         movem.l (sp)+,d2-d7/a2-a6
  1488.         rts
  1489.  
  1490. 3$      movem.l d2-d7/a2-a6,-(sp)
  1491.         move.l  modmem(a4),a5
  1492.         jsr     8(a5)
  1493.         movem.l (sp)+,d2-d7/a2-a6
  1494.         rts
  1495.  
  1496. 5$      movem.l d2-d7/a2-a6,-(sp)
  1497.         jsr     4(a1)
  1498.         movem.l (sp)+,d2-d7/a2-a6
  1499.         rts
  1500.  
  1501. *** fxstart - Code for SoundFX modules
  1502. fxstart:
  1503.         movem.l a5/a6,-(sp)
  1504.         move.l  modmem(a4),a5
  1505.         move.l  _SysBase(a4),a6
  1506.  
  1507.         lea     $80(a5),a0              ; Make sure it's a SoundFX module
  1508.         move.w  #($a20-$80)/4-1,d0
  1509.         moveq   #0,d1
  1510. 1$      add.l   (a0)+,d1
  1511.         dbra    d0,1$
  1512.         cmpi.l  #$97adddd8,d1
  1513.         bne     diecorrupt
  1514.  
  1515.         move.l  $20(a5),d0              ; Relocate the player
  1516.         add.l   d0,d0
  1517.         add.l   d0,d0
  1518.         cmp.l   modsize(a4),d0
  1519.         bge     diecorrupt
  1520.         lea     $30(a5,d0.l),a0
  1521.         cmpi.l  #$3ec,-$c(a0)
  1522.         bne     diecorrupt
  1523.         moveq   #49-1,d0
  1524.         lea     $24(a5),a1
  1525.         move.l  a1,d2
  1526. 12$     move.l  (a0)+,d1
  1527.         add.l   d2,0(a1,d1.l)
  1528.         dbra    d0,12$
  1529.  
  1530.         move.l  #$4e714e71,$196(a5)     ; NOP out AddICRVector
  1531.         move.l  #$4e714e71,$1a8(a5)     ; NOP out call to set CIA stuff
  1532.  
  1533.         bsr     clearcache
  1534.  
  1535.         movem.l (sp)+,a5/a6
  1536.         plstartret 9$
  1537.  
  1538. 2$      movem.l d2-d7/a2-a6,-(sp)       ; Jump into player start code
  1539.         move.l  modmem(a4),a0
  1540.         jsr     $13e(a0)
  1541.         movem.l (sp)+,d2-d7/a2-a6
  1542.         rts
  1543.  
  1544. 5$      move.l  modmem(a4),a0           ; Calculate interrupt frequency
  1545.         move.l  #715909,d0
  1546.         divu.w  $a64(a0),d0
  1547.         ext.l   d0
  1548.         rts
  1549.  
  1550.         cnop    0,4
  1551.         dc.l    gmod_Hook
  1552. 9$      gmodnop
  1553.         gmodbra 2$                      ; StartMusic
  1554.         gmodnop
  1555.         gmodnop
  1556.         gmodnop
  1557.         gmodq   1
  1558.         gmodnop
  1559.         gmodnop
  1560.         gmodnop
  1561.         gmodnop
  1562.         gmodnop
  1563.         gmodnop
  1564.         gmodnop
  1565.         gmodnop
  1566.         gmodnop
  1567.         gmodbra 5$                      ; GetFrequency
  1568.         jmp     $466(a1)                ; TimerTick
  1569.         lea     fxname(a4),a0           ; GetMakerName
  1570.         move.l  a0,d0
  1571.         rts
  1572.  
  1573. *** whitstart - Code for Dave Whittaker modules
  1574. dwinitentry     equ     $00
  1575. dwvbentry       equ     $0e
  1576. dwendentry      equ     $1c
  1577.  
  1578. whitstart:
  1579.         moveq   #6-1,d0         ; Make sure it's really a DW module
  1580. 1$      move.w  $0(a0),d1
  1581.         add.w   $4(a0),d1
  1582.         add.w   $8(a0),d1
  1583.         add.w   $c(a0),d1
  1584.         cmpi.w  #$453b,d1
  1585.         bne     diecorrupt
  1586.         adda.w  #$e,a0
  1587.         dbra    d0,1$
  1588.  
  1589.         plstartret 9$
  1590.  
  1591.         cnop    0,4
  1592.         dc.l    gmod_Hook
  1593. 9$      gmodnop
  1594.         gmodbra 2$                      ; StartMusic
  1595.         gmodbra 3$                      ; StopMusic
  1596.         gmodnop
  1597.         gmodnop
  1598.         gmodnop
  1599.         gmodnop
  1600.         gmodnop
  1601.         gmodnop
  1602.         gmodnop
  1603.         gmodnop
  1604.         gmodnop
  1605.         gmodnop
  1606.         gmodnop
  1607.         gmodnop
  1608.         gmodbra getfreqmodspeed         ; GetFrequency
  1609.         jmp     dwvbentry(a1)           ; TimerTick
  1610.         lea     whitname(a4),a0         ; GetMakerName
  1611.         move.l  a0,d0
  1612.         rts
  1613.  
  1614. 2$      move.l  modmem(a4),a0
  1615.         jmp     dwinitentry(a0)
  1616.  
  1617. 3$      move.l  modmem(a4),a0
  1618.         jmp     dwendentry(a0)
  1619.  
  1620. *** deltastart - Code for Delta Music modules
  1621. deltastart:
  1622.         plstartret 9$
  1623.  
  1624.         cnop    0,4
  1625.         dc.l    gmod_Hook
  1626. 9$      gmodnop
  1627.         gmodbra 2$                      ; StartMusic
  1628.         gmodnop
  1629.         gmodnop
  1630.         gmodnop
  1631.         gmodnop
  1632.         gmodnop
  1633.         gmodnop
  1634.         gmodnop
  1635.         gmodnop
  1636.         gmodnop
  1637.         gmodnop
  1638.         gmodnop
  1639.         gmodnop
  1640.         gmodnop
  1641.         gmodbra getfreqmodspeed         ; GetFrequency
  1642.         gmodbra 4$                      ; TimerTick
  1643.         lea     deltaname(a4),a0        ; GetMakerName
  1644.         move.l  a0,d0
  1645.         rts
  1646.  
  1647. 2$      push    d2-d7/a2-a6
  1648.         move.l  modmem(a4),a0
  1649.         moveq   #1,d0
  1650.         jsr     (a0)
  1651.         pop     d2-d7/a2-a6
  1652.         rts
  1653.  
  1654. 4$      push    d2-d7/a2-a6
  1655.         moveq   #0,d0
  1656.         jsr     (a1)
  1657.         pop     d2-d7/a2-a6
  1658.         rts
  1659.  
  1660. delta2start:                            ; Different version (older probably)
  1661.         plstartret 9$
  1662.  
  1663.         cnop    0,4
  1664.         dc.l    gmod_Hook
  1665. 9$      gmodnop
  1666.         gmodbra 2$                      ; StartMusic
  1667.         gmodnop
  1668.         gmodnop
  1669.         gmodnop
  1670.         gmodnop
  1671.         gmodnop
  1672.         gmodnop
  1673.         gmodnop
  1674.         gmodnop
  1675.         gmodnop
  1676.         gmodnop
  1677.         gmodnop
  1678.         gmodnop
  1679.         gmodnop
  1680.         gmodbra getfreqmodspeed         ; GetFrequency
  1681.         gmodbra 4$                      ; TimerTick
  1682.         lea     deltaname(a4),a0        ; GetMakerName
  1683.         move.l  a0,d0
  1684.         rts
  1685.  
  1686. 2$      push    d2-d7/a2-a6
  1687.         move.l  modmem(a4),a0
  1688.         jsr     (a0)
  1689.         pop     d2-d7/a2-a6
  1690.         rts
  1691.  
  1692. 4$      push    d2-d7/a2-a6
  1693.         jsr     $17c(a1)
  1694.         pop     d2-d7/a2-a6
  1695.         rts
  1696.  
  1697. *** sid2start - Code for SidMon modules
  1698. sid2start:
  1699.         plstartret 9$
  1700.  
  1701.         cnop    0,4
  1702.         dc.l    gmod_Hook
  1703. 9$      gmodnop
  1704.         gmodbra 2$                      ; StartMusic
  1705.         gmodnop
  1706.         gmodnop
  1707.         gmodnop
  1708.         gmodnop
  1709.         gmodnop
  1710.         gmodnop
  1711.         gmodnop
  1712.         gmodnop
  1713.         gmodnop
  1714.         gmodnop
  1715.         gmodnop
  1716.         gmodnop
  1717.         gmodnop
  1718.         gmodbra getfreqmodspeed         ; GetFrequency
  1719.         jmp     $16a(a1)                ; TimerTick
  1720.         lea     sidname(a4),a0          ; GetMakerName
  1721.         move.l  a0,d0
  1722.         rts
  1723.  
  1724. 2$      move.l  modmem(a4),a0           ; Put an RTS after the interrupt routine
  1725.         move.w  #$4e75,$25c(a0)
  1726.         bsr     clearcache
  1727.  
  1728.         move.l  modmem(a4),a0           ; Call the initialization routine
  1729.         push    d2-d7/a2-a6
  1730.         jsr     $2c(a0)
  1731.         pop     d2-d7/a2-a6
  1732.         rts
  1733.  
  1734. *** markiistart - Code for Mark II modules
  1735. markiistart:
  1736.         cmpi.l  #$41fa035e,4(a0)        ; Check a little more...
  1737.         bne     diecorrupt
  1738.  
  1739.         plstartret 9$
  1740.  
  1741.         cnop    0,4
  1742.         dc.l    gmod_Hook
  1743. 9$      gmodnop
  1744.         gmodbra 2$                      ; StartMusic
  1745.         gmodnop
  1746.         gmodnop
  1747.         gmodnop
  1748.         gmodnop
  1749.         gmodnop
  1750.         gmodnop
  1751.         gmodnop
  1752.         gmodnop
  1753.         gmodnop
  1754.         gmodnop
  1755.         gmodnop
  1756.         gmodnop
  1757.         gmodnop
  1758.         gmodbra getfreqmodspeed         ; GetFrequency
  1759.         gmodbra 3$                      ; TimerTick
  1760.         lea     markiiname(a4),a0       ; GetMakerName
  1761.         move.l  a0,d0
  1762.         rts
  1763.  
  1764. 2$      move.l  modmem(a4),a0
  1765.         moveq   #-1,d0
  1766.         push    d2-d7/a2-a6
  1767.         jsr     (a0)
  1768.         pop     d2-d7/a2-a6
  1769.         rts
  1770.  
  1771. 3$      moveq   #0,d0
  1772.         push    d2-d7/a2-a6
  1773.         jsr     (a1)
  1774.         pop     d2-d7/a2-a6
  1775.         rts
  1776.  
  1777. *** ftmstart - Code for Face The Music modules
  1778.  
  1779. ftm_init        equ     4
  1780. ftm_end         equ     8
  1781. ftm_load        equ     12              ; d0 = filename, returns nonzero = success
  1782. ftm_unload      equ     16
  1783. ftm_play        equ     20
  1784. ftm_stop        equ     24
  1785. ftm_set1        equ     28
  1786. ftm_set2        equ     32
  1787. ftm_get1        equ     36
  1788. ftm_get2        equ     40
  1789. ftm_waitdone    equ     44
  1790. ftm_get3        equ     48
  1791. ftm_ccall       equ     52
  1792.  
  1793. ftmstart:
  1794.         apush4
  1795.  
  1796.         st.b    noaudalloc(a4)
  1797.  
  1798.         lea     modspec(a4),a0          ; We can't use the already-loaded module!
  1799.         bsr     unloadfile
  1800.  
  1801.         move.l  _DOSBase(a4),a6         ; Load PlayFTM
  1802.         lea     playftmname(a4),a0
  1803.         move.l  a0,d1
  1804.         jl      LoadSeg
  1805.         move.l  d0,ftmseg(a4)
  1806.         bz.b    \noplayer
  1807.  
  1808.         lsl.l   #2,d0                   ; Find jump table (a5, ftmtab)
  1809.         addq.l  #4,d0
  1810.         move.l  d0,ftmtab(a4)
  1811.         move.l  d0,a5
  1812.  
  1813.         jsr     ftm_init(a5)            ; Initialize PlayFTM
  1814.  
  1815.         move.l  modfile(a4),d0          ; Re-load the module through PlayFTM
  1816.         jsr     ftm_load(a5)
  1817.         tst.l   d0
  1818.         bz      \corrupt
  1819.  
  1820.         apop4
  1821.         plstartret 9$
  1822.  
  1823. \noplayer
  1824.         lea     ftmnoplayer(a4),a0
  1825.         bra     diemes
  1826.  
  1827. \corrupt
  1828.         lea     corrcomp(a4),a0
  1829.         bra     diemes
  1830.  
  1831. \start
  1832.         moveq   #0,d0                      ; Start playing
  1833.         moveq   #0,d1
  1834.         moveq   #0,d2
  1835.         moveq   #0,d3
  1836.         move.l  ftmtab(a4),a0
  1837.         jmp     ftm_play(a0)
  1838.  
  1839. \stop
  1840.         move.l  ftmtab(a4),a0
  1841.         jmp     ftm_stop(a0)
  1842.  
  1843. \end
  1844.         move.l  ftmtab(a4),a0
  1845.         jsr     ftm_unload(a0)
  1846.         jmp     ftm_end(a0)
  1847.  
  1848.         cnop    0,4
  1849.         dc.l    gmod_Hook
  1850. 9$      gmodnop
  1851.         gmodbra \start
  1852.         gmodbra \stop
  1853.         gmodbra \end
  1854.         gmodnop
  1855.         gmodnop
  1856.         gmodnop
  1857.         gmodnop
  1858.         gmodnop
  1859.         gmodnop
  1860.         gmodnop
  1861.         gmodnop
  1862.         gmodnop
  1863.         gmodnop
  1864.         gmodnop
  1865.         gmodnop
  1866.         gmodnop
  1867.         lea     ftmname(a4),a0          ; GetMakerName
  1868.         move.l  a0,d0
  1869.         rts
  1870.  
  1871. *** unloadftm - FIXME - KLUDGE - unload the FTM player (called by main.c)
  1872.         xdef    _unloadftm
  1873. _unloadftm
  1874.         apush4
  1875.         move.l  _DOSBase(a4),a6
  1876.         move.l  ftmseg(a4),d1
  1877.         bz.b    1$
  1878.         jl      UnLoadSeg
  1879. 1$      apop4
  1880.         rts
  1881.  
  1882.  
  1883. *** setnormtint - Set the timer interrupt using the current module's default speed
  1884. * a0 = Pointer to interrupt routine to be called on interrupts
  1885. * a1 = Data that should appear in register a1 on interrupt calls
  1886. setnormtint:
  1887.         moveq   #50,d0
  1888.         ; fall through...
  1889. *** settint - Set the timer interrupt
  1890. * a0 = Pointer to interrupt routine to be called on interrupts
  1891. * a1 = Data that should appear in register a1 on interrupt calls
  1892. * d0 = Number of ticks per second (frequency) to call interrupt routine
  1893. settint:
  1894.         movem.l a2/a3,-(sp)
  1895.  
  1896.         move.l  a0,sint+IS_CODE(a4)     ; Initialize the timer interrupt
  1897.         move.l  a1,sint+IS_DATA(a4)
  1898.         move.b  #NT_INTERRUPT,d1
  1899.         move.b  d1,sint+LN_TYPE(a4)
  1900.         move.b  d1,tint+LN_TYPE(a4)
  1901.         lea     sint(a4),a0
  1902.         move.l  a0,tint+IS_DATA(a4)
  1903.         move.l  _SysBase(a4),a0
  1904.         lea     _LVOCause(a0),a0
  1905.         move.l  a0,tint+IS_CODE(a4)
  1906.  
  1907.         move.w  d0,-(sp)
  1908.  
  1909.         move.l  _BattMemBase(a4),a6
  1910.         lea     tint(a4),a1             ; First try to get timer B
  1911.         moveq   #CIAICRB_TB,d0
  1912.         move.b  d0,timernum(a4)
  1913.         move.l  #CIAB+ciatblo,a2
  1914.         move.l  a2,timerlo(a4)
  1915.         move.l  #CIAB+ciacrb,a3
  1916.         jsr     _LVOAddICRVector(a6)
  1917.         tst.l   d0
  1918.         beq.s   1$
  1919.  
  1920.         lea     tint(a4),a1             ; Already taken - try timer A
  1921.         moveq   #CIAICRB_TA,d0
  1922.         move.b  d0,timernum(a4)
  1923.         move.l  #CIAB+ciatalo,a2
  1924.         move.l  a2,timerlo(a4)
  1925.         move.l  #CIAB+ciacra,a3
  1926.         jsr     _LVOAddICRVector(a6)
  1927.         tst.l   d0
  1928.         bne     dienotimer
  1929. 1$
  1930.         and.b   #%11000000,(a3)         ; Set the control register
  1931.         tst.b   timernum(a4)
  1932.         beq.s   3$
  1933.         bclr    #6,(a3)
  1934. 3$
  1935.         move.w  (sp)+,d0                ; Set the timer frequency
  1936.         bsr     changetint
  1937.  
  1938.         bset    #0,(a3)                 ; Start the timer
  1939.  
  1940.         movem.l (sp)+,a2-a3
  1941.  
  1942.         move.b  timernum(a4),d1         ; Enable the timer interrupt
  1943.         moveq   #-$80,d0
  1944.         bset    d1,d0
  1945.         jmp     _LVOAbleICR(a6)
  1946.  
  1947. *** changetint - Change the timer interrupt speed (callable from an interrupt)
  1948. * d0 = New frequency (Hz)
  1949. * All registers saved
  1950. changetint:
  1951.         tst.l   tint+IS_CODE
  1952.         bz.b    9$
  1953.         push    d0-d1/a0-a1
  1954.         lea     _LinkerDB,a1
  1955.  
  1956.         move.w  d0,tintfreq(a1)         ; Store the new frequency
  1957.  
  1958.         tst.l   tint+IS_CODE(a1)
  1959.         bz.b    9$
  1960.  
  1961.         mulu.w  mastfreq(a1),d0
  1962.         lsr.l   #8,d0
  1963.         bz.b    \zero
  1964.  
  1965.         move.l  clockfreq(a1),d1        ; Poke the new timer value
  1966.         divu.w  d0,d1
  1967.         move.l  timerlo(a1),a0
  1968.         move.b  d1,(a0)
  1969.         lsr.w   #8,d1
  1970.         move.b  d1,$100(a0)
  1971. \zero
  1972.         pop     d0-d1/a0-a1
  1973. 9$      rts
  1974.  
  1975. *** changetintcia - Change the timer interrupt speed (callable from an interrupt)
  1976. * d0 = CIA speed value
  1977. * All registers saved
  1978. changetintcia:
  1979.         push    d0-d1/a0-a1
  1980.         lea     _LinkerDB,a1
  1981.  
  1982.         tst.l   tint+IS_CODE(a1)
  1983.         bz.b    9$
  1984.  
  1985.         move.l  timerlo(a1),a0          ; Poke the new timer value
  1986.         moveq   #0,d1
  1987.         move.w  d0,d1
  1988.         lsl.l   #8,d1
  1989.         divu.w  mastfreq(a1),d1
  1990.         move.b  d1,(a0)
  1991.         lsr.w   #8,d1
  1992.         move.b  d1,$100(a0)
  1993.  
  1994.         move.l  clockfreq(a1),d1        ; Find the new frequency to display
  1995.         divu.w  d0,d1
  1996.         move.w  d1,tintfreq(a1)
  1997.  
  1998. 9$      pop     d0-d1/a0-a1
  1999.         rts
  2000.  
  2001. *** stoptint - Stop the timer interrupt if it was installed
  2002. stoptint:
  2003.         tst.l   tint+IS_CODE(a4)        ; Make sure it was installed
  2004.         beq.s   9$
  2005.         moveq   #0,d0                   ; Remove the interrupt handler
  2006.         move.b  timernum(a4),d0
  2007.         lea     tint(a4),a1
  2008.         move.l  _BattMemBase(a4),a6
  2009.         jsr     _LVORemICRVector(a6)
  2010.         clr.l   tint+IS_CODE(a4)
  2011. 9$      rts
  2012.  
  2013.  
  2014.  
  2015. *** playervolume - Update the master volume for the currently playing module
  2016. playervolume
  2017. _playervolume
  2018.         apush4
  2019.  
  2020.         tst.b   _playing(a4)            ; Make sure we're playing something
  2021.         bz      \out
  2022.  
  2023.         move.w  mbalance(a4),d2         ; Find the new overall volume (d0)
  2024.         move.w  balance(a4),d3
  2025.         move.w  mvolume(a4),d1
  2026.         move.w  volume(a4),d0
  2027.         bpl.b   \hasvol
  2028.         moveq   #100,d0
  2029.         moveq   #100,d1
  2030.         moveq   #0,d2
  2031.         moveq   #0,d3
  2032. \hasvol
  2033.         mulu.w  d1,d0
  2034.         lsl.l   #8,d0
  2035.         divu.w  #10000,d0
  2036.         move.w  d0,d1
  2037.  
  2038.         tst.w   d2                      ; Adjust for master balance
  2039.         bz.b    \mgot
  2040.         bmi.b   \mmoreleft
  2041. \mmoreright
  2042.         neg.w   d2
  2043.         add.w   #50,d2
  2044.         mulu.w  d2,d0
  2045.         divu.w  #50,d0
  2046.         bra.b   \mgot
  2047. \mmoreleft
  2048.         add.w   #50,d2
  2049.         mulu.w  d2,d1
  2050.         divu.w  #50,d1
  2051. \mgot
  2052.  
  2053.         tst.w   d3                      ; Adjust for module balance
  2054.         bz.b    \got
  2055.         bmi.b   \moreleft
  2056. \moreright
  2057.         neg.w   d3
  2058.         add.w   #50,d3
  2059.         mulu.w  d3,d0
  2060.         divu.w  #50,d0
  2061.         bra.b   \got
  2062. \moreleft
  2063.         add.w   #50,d3
  2064.         mulu.w  d3,d1
  2065.         divu.w  #50,d1
  2066. \got
  2067.  
  2068.         move.w  _fadevol(a4),d2         ; Adjust for fading
  2069.         bmi.b   \nofade
  2070.         mulu.w  d2,d0
  2071.         lsr.w   #7,d0
  2072.         mulu.w  d2,d1
  2073.         lsr.w   #7,d1
  2074. \nofade
  2075.  
  2076.         tst.b   portablemodule(a4)      ; Tell the module about the new volume
  2077.         bnz     \portavol
  2078.         move.l  gmodptr(a4),a5
  2079.         moveq   #gmod_SetVolume,d2
  2080.         gmodmaycall d2
  2081.         bra     \out
  2082. \portavol
  2083.         bsr     NoteSysMasterVolBal
  2084. \out
  2085.         apop4
  2086.         rts
  2087.  
  2088. *** playerspeed - Update the master speed
  2089. playerspeed
  2090. _playerspeed
  2091.         push    a6
  2092.  
  2093.         move.w  speed(a4),d0            ; Calculate the new relative speed
  2094.         bnz.b   \ok
  2095.         moveq   #50,d0
  2096. \ok
  2097.         move.w  mspeed(a4),d1
  2098.         mulu.w  d1,d0
  2099.         lsl.l   #8,d0
  2100.         divu.w  #50*50,d0
  2101.         move.w  d0,mastfreq(a4)
  2102.  
  2103.         move.l  _SysBase(a4),a6         ; Set the new speed
  2104.         jl      Disable
  2105.         move.w  tintfreq(a4),d0
  2106.         bsr     changetint
  2107.         jl      Enable
  2108.  
  2109.         pop     a6
  2110.         rts
  2111.  
  2112.  
  2113. *** jumpforward - Jump one sequence forward in the module
  2114. jumpforward
  2115.         move.l  gmodptr(a4),d0
  2116.         bz      \out
  2117.         push    d5/a5
  2118.         move.l  d0,a5
  2119.         moveq   #0,d0
  2120.         move.l  songpos(a4),d1
  2121.         addq.l  #1,d1
  2122.         moveq   #gmod_Jump,d5
  2123.         gmodmaycall d5
  2124.         pop     d5/a5
  2125. \out
  2126.         rts
  2127.  
  2128. *** jumpback - Jump one sequence backward in the module
  2129. jumpback
  2130.         move.l  gmodptr(a4),d0
  2131.         bz      \out
  2132.         push    d5/a5
  2133.         move.l  d0,a5
  2134.         moveq   #0,d0
  2135.         move.l  songpos(a4),d1
  2136.         bz.b    \out1
  2137.         subq.l  #1,d1
  2138.         moveq   #gmod_Jump,d5
  2139.         gmodmaycall d5
  2140. \out1
  2141.         pop     d5/a5
  2142. \out
  2143.         rts
  2144.  
  2145.  
  2146. *** iscantcont - See if an error is a 'can't continue' error
  2147. * a0 = Pointer to message in question
  2148. * Returns: d0 = nonzero if a0 is a can't continue error
  2149. _iscantcont
  2150.         move.l  4(sp),a0
  2151. iscantcont
  2152.         moveq   #0,d0
  2153.         lea     nocontinue(a4),a1
  2154.         cmp.l   a1,a0
  2155.         seq     d0
  2156.         rts
  2157.  
  2158. *** dmawait - DMA delay wait
  2159. dmawait:
  2160.         movem.l d0-d1,-(sp)
  2161.         moveq   #7-1,d1
  2162. 1$      move.b  $dff006,d0
  2163. 2$      cmp.b   $dff006,d0
  2164.         beq.s   2$
  2165.         dbf     d1,1$
  2166.         movem.l (sp)+,d0-d1
  2167.         rts
  2168.  
  2169.  
  2170. *** clearcache - Clear the code cache
  2171. clearcache:
  2172.         move.l  a6,-(sp)
  2173.         move.l  4,a6
  2174.         cmpi.w  #36,LIB_VERSION(a6)
  2175.         bcs.s   13$
  2176.         jsr     _LVOCacheClearU(a6)
  2177. 13$     move.l  (sp)+,a6
  2178.         rts
  2179.  
  2180.  
  2181.         data    __MERGED
  2182.  
  2183. _numsongs:
  2184. numsongs        dc.l    1               ; Number of songs in this module
  2185. _cursong:
  2186. cursong         dc.l    0               ; Current song number
  2187.  
  2188. playerhook      dc.l    0,0,hookfunc    ; Hook to send to modules
  2189.  
  2190. mastfreq        dc.w    $100            ; Master relative frequency ($100=normal)
  2191.  
  2192. _fadevol        dc.w    -1              ; Current fade volume
  2193.  
  2194.                 even
  2195. gmodname        dc.b    "GMOD ("
  2196. gmodnametype    dc.l    0
  2197.                 dc.b    ")",0
  2198.  
  2199. nocmem          dc.b    "Not enough chip memory",0
  2200. nomemtext       dc.b    "Not enough memory",0
  2201. unkmod          dc.b    "Unknown module type",0
  2202. cormod          dc.b    "Corrupt module",0
  2203. errplay         dc.b    "Error playing module",0
  2204. nofile          dc.b    "Can't load module",0
  2205. noabs           dc.b    "Required memory occupied",0
  2206. notimer         dc.b    "No CIAB timers available",0
  2207. dontcompress    dc.b    "Please decompress this module",0
  2208. genembname      dc.b    "Generic embedded-player",0
  2209. xmodname        dc.b    "XMOD/AMOD",0
  2210. whitname        dc.b    "Dave Whittaker",0
  2211. deltaname       dc.b    "Delta Music",0
  2212. sidname         dc.b    "SidMon",0
  2213. markiiname      dc.b    "Mark II",0
  2214. fxname          dc.b    "SoundFX",0
  2215. unknowntxt      dc.b    "Unknown",0
  2216. notloaded       dc.b    "No module loaded",0
  2217. nocontinue      dc.b    "Module cannot continue",0
  2218. audiointname    dc.b    "MultiPlayer audio interrupt",0
  2219. playftmname     dc.b    "PlayFTM:",0
  2220. ftmnoplayer     dc.b    "Can't load Face The Music player",0
  2221. corrcomp        dc.b    "Corrupt (or compressed) FTM module",0
  2222. ftmname         dc.b    "Face The Music"
  2223. nulllab         dc.b    0
  2224.  
  2225.         bss     __MERGED
  2226.  
  2227. stackpt         ds.l    1               ; Stack pointer when we die while loading
  2228. loadhan         ds.l    1               ; Handle currently being loaded
  2229. gmodptr         ds.l    1               ; Pointer to real or fake GMOD structure
  2230.  
  2231. modspec:                                ; Currently loaded module
  2232. modmem          ds.l    1
  2233. modsize         ds.l    1
  2234. modend          ds.l    1
  2235. modalloc        ds.l    1
  2236.  
  2237. suppspec:                               ; Supplemental data file (Startrekker, TFMX)
  2238. suppmem         ds.l    1
  2239. suppsize        ds.l    1
  2240. suppend         ds.l    1
  2241. suppalloc       ds.l    1
  2242.  
  2243. modfile         ds.l    1               ; Filename of module
  2244. _modname:
  2245. modname         ds.l    1               ; Displayed name of module
  2246. modfilesize     ds.l    1               ; Allocated size of modfile
  2247.  
  2248. _authorname:
  2249. authorname      ds.l    1               ; Name of song's author
  2250. _modtypename:
  2251. modtypename     ds.l    1               ; Type of module
  2252. _songcatalog:
  2253. songcatalog     ds.l    1               ; Catalog of song names for current module
  2254. _infolist:
  2255. infolist        ds.l    1               ; List of information lines for Info window
  2256.  
  2257. cursongprefs    ds.l    1               ; Pointer into songprefs for current song
  2258.  
  2259. clockfreq       ds.l    1               ; CIA clock frequency
  2260.  
  2261. _songtime       ds.l    1               ; Number of VBlanks this song has played
  2262. _songendtime    ds.l    1               ; When this song should end
  2263.  
  2264. _songpos
  2265. songpos         ds.l    1               ; Current sequence number
  2266. _songlen
  2267. songlen         ds.l    1               ; Total number of sequences in song
  2268.  
  2269. ntauthor        ds.l    1               ; Author name from NoiseTracker modules
  2270.  
  2271. ftmseg          ds.l    1               ; SegList of PlayFTM
  2272. ftmtab          ds.l    1               ; FTM jump table
  2273.  
  2274. timerlo         ds.l    1               ; Address of CIA timer low counter register
  2275.  
  2276. audints         ds.b    IS_SIZE*4       ; Audio channel interrupts
  2277. audisave        ds.l    4               ; Previous interrupt vectors
  2278.  
  2279. modremember     ds.l    1               ; Remember list attached to this module
  2280.  
  2281. tint            ds.b    IS_SIZE
  2282. sint            ds.b    IS_SIZE
  2283.  
  2284. tintfreq        ds.w    1               ; Timer interrupt frequency (un-user-adjusted)
  2285.  
  2286. _fadeinc        ds.w    1               ; +1 or -1 - which way to fade
  2287.  
  2288. xpkerrmsg       ds.b    80              ; Buffer for XPK error messages
  2289.  
  2290. _playing        ds.b    1               ; Module is currently playing
  2291. noaudalloc      ds.b    1               ; Don't allocate the audio hardware
  2292.  
  2293. timernum        ds.b    1               ; Which CIAB timer we got
  2294.  
  2295. _modtype
  2296. modtype         ds.b    1               ; Module type flags
  2297.  
  2298. portablemodule  ds.b    1               ; Nonzero if we're playing a portable module
  2299.  
  2300.         end
  2301.